﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Rabbit.BusinessLogicLayer;
using Rabbit.Model;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using Rabbit.Utils;
using Rabbit.Themes;

namespace MicroBlogClient
{
    /// <summary>
    /// Interaction logic for UCLogin.xaml
    /// </summary>
    public partial class UCLogin : UserControl
    {
        Properties.Settings settings = new Properties.Settings();
        public static RoutedEvent OnLoginFinishedEvent = EventManager.RegisterRoutedEvent(
           "OnLoginFinished", RoutingStrategy.Bubble, typeof(OneValueEventHandler<bool>), typeof(UCLogin));
        public event OneValueEventHandler<bool> OnLoginFinished
        {
            add { AddHandler(OnLoginFinishedEvent, value); }
            remove { RemoveHandler(OnLoginFinishedEvent, value); }
        }

        public UCLogin()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(UCLogin_Loaded);
            this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(UCLogin_IsVisibleChanged);
        }

        void UCLogin_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue)
            {
                LoadUserList();
                txtUserName.SelectedIndex = 0;
            }
        }

        void UCLogin_Loaded(object sender, RoutedEventArgs e)
        {
            RequestHelper.SetOAuthBaseUrl(
            Application.Current.Resources["RequestTokenUrl"].ToString(),
            Application.Current.Resources["AuthorizationTokenUrl"].ToString(),
            Application.Current.Resources["AccessTokenUrl"].ToString(),
            Application.Current.Resources["ConsumerKey"].ToString(),
            Application.Current.Resources["ConsumerSecret"].ToString(),
            Application.Current.Resources["APIBaseUrl"].ToString()
          );

           RequestHelper.UserStatusServerApiUrl = Application.Current.Resources["UserStatusServerUrl"].ToString();
           txtUserName.Focus();
        }
        private void LoadUserList()
        {
            try
            {
                settings.Reload();
                if (settings.UserList == null)
                {
                    settings.UserList = new UserSettingList();
                }
                 
                settings.UserList.Sort();

                txtUserName.ItemsSource = settings.UserList;
            }
            catch (Exception ex)
            {
                LogHelper.LogError(ex);
                try
                {
                    System.IO.File.Delete((ex.InnerException as System.Configuration.ConfigurationException).Filename);
                    settings.Reload();
                    settings.Save();
                }
                catch (Exception)
                {
                }
            }
        }
        bool IsCancel = false;
        private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            if (chkNewUser.IsChecked.Value)
            {
                if (txtVerifyCode.Text.Length == 0)
                {
                    txtVerifyCode.Focus();
                    return;
                }
            }
            else
            {
                if (txtUserName.Text.Length == 0)
                {
                    txtUserName.Focus();
                    return;
                }
                if (txtPassword.Password.Length == 0)
                {
                    txtPassword.Focus();
                    return;
                }
            }
            bool isLoginByVerifyCode = chkNewUser.IsChecked.Value;
            string verifyCode = txtVerifyCode.Text;
            UserStatus status = chkIsOnline.IsChecked.Value ? UserStatus.Online : UserStatus.Hidden;

            bool IsRememberPassword = chkRememberPassword.IsChecked.Value;
            string userName = txtUserName.Text;
            string password = txtPassword.Password;
            cancelPanel.Visibility = System.Windows.Visibility.Visible;
            panelUserAccount.Visibility = System.Windows.Visibility.Collapsed;
            IsCancel = false;

            Action generateAccessToken = new Action(() =>
            {
                try
                {
                    if (isLoginByVerifyCode)
                    {
                        RequestHelper.GenerateAccessToken(verifyCode);
                    }
                    else
                    {
                        RequestHelper.GetAccessTokenByUsernameAndPassword(userName, password);
                    }

                    Debug.Print("IsCancel before GetCurrentUserInformation:" + IsCancel);
                    if (IsCancel)
                    {
                        return;
                    }

                    UserBL.GetCurrentUserInformation();

                    Debug.Print("IsCancel after GetCurrentUserInformation:" + IsCancel);
                    if (IsCancel)
                    {
                        return;
                    }

                    if (settings.UserList == null)
                    {
                        settings.UserList = new UserSettingList();
                        settings.Save();
                    }

                    int settingsLocation = settings.UserList.FindIndex(u => u.UserID == UserBL.CurrentUser.Id);
                    UserSettings userSettings;

                    if (settingsLocation != -1)
                    {
                        userSettings = settings.UserList[settingsLocation];


                        //check UserSetting's field, and compare it's value with current saved userSetting
                        //if the value of current userSetting is null, set its default value to be the the default value of UserSetting class
                        //Type UserSettingsType = typeof(UserSettings);
                        //var properties = UserSettingsType.GetProperties();
                        //foreach (var property in properties)
                        //{
                        //    string propertyName = property.Name;
                        //    if (UserSettingsType.GetProperty(propertyName).GetValue(userSettings, null) == null)
                        //    {
                        //        UserSettingsType.GetProperty(propertyName).SetValue(userSettings, settings[propertyName], null);
                        //    }
                        //}
                        userSettings.LastAccessTime = DateTime.Now;
                        settings.UserList[settingsLocation] = userSettings;
                    }
                    else
                    {
                        //load default settings from user.config
                        userSettings = new UserSettings()
                        {
                            LastAccessTime = DateTime.Now,
                            UserName = userName,
                            PopupForMetionedMe = settings.PopupForMetionedMe,
                            PopupForNewComment = settings.PopupForNewComment,
                            PopupForNewStatus = settings.PopupForNewStatus,
                            Theme = settings.Theme,
                            HelpPublicizing = settings.HelpPublicizing,
                            UpdateInterval = settings.UpdateInterval,
                            UserID = UserBL.CurrentUser.Id,
                            TokenSecret = Rabbit.Utils.Common.EncryptString(password),
                            MainWindowOpacity = settings.MainWindowOpacity,
                            MainWindowBackgroundOpacity = settings.MainWindowBackgroundOpacity,
                            PopupMessageShowTime = settings.PopupMessageShowTime,
                            IsTwinkleSysTrayIcon = settings.IsTwinkleSysTrayIcon,
                            CaptureScreenHotKey = settings.CaptureScreenHotKey,
                            GetCommentHotKey = settings.GetCommentHotKey,
                            GetLetterHotKey = settings.GetLetterHotKey,
                            GetStatusHotKey = settings.GetStatusHotKey,
                            GetMetionedMeHotKey = settings.GetMetionedMeHotKey,
                            IsPlayingSound = settings.IsPlayingSound,
                            PopupForNewLetter = settings.PopupForNewLetter,
                            MyFollowingNameList = settings.MyFollowingNameList
                        };
                        settings.UserList.Add(userSettings);
                    }

                    if (!isLoginByVerifyCode)
                    {
                        userSettings.TokenSecret = IsRememberPassword ? Rabbit.Utils.Common.EncryptString(password):string.Empty;
                    }
                     
                    UserBL.CurrentUser.UserSettings = userSettings;
                    settings.Save();
                }
                catch (MaxRatesExceededException ex)
                {
                    MessageBox.Show("超过最大次数访问上限,暂时无法使用该软件。\r\n该限制将在" + ex.RatesInformation.ResetTime + "后自动解除");
                    return;
                }
                catch (Exception ex)
                {
                    LogHelper.LogError(ex);
                    MessageBox.Show("登录失败,请检查用户名密码是否输入错误");
                    return;
                }
                finally
                {
                    ResetPanelStatus();
                }

                this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    if (UserBL.CurrentUser != null)
                    {
                        UserBL.UpdateUserStatus(UserBL.CurrentUser, status);
                        App.Current.ApplyTheme(UserBL.CurrentUser.UserSettings.Theme);
                        RaiseEvent(new OneValueEventArgs<bool>(OnLoginFinishedEvent) { Value = true });
                    }
                }), System.Windows.Threading.DispatcherPriority.Send);
            });

            generateAccessToken.BeginInvoke(null, null);
        }

        private void ResetPanelStatus()
        {
            this.Dispatcher.BeginInvoke(new Action(()=>{
                 cancelPanel.Visibility = System.Windows.Visibility.Collapsed;
                panelUserAccount.Visibility = System.Windows.Visibility.Visible;
            }), System.Windows.Threading.DispatcherPriority.ContextIdle);
        }

        private void UserControl_PreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnLogin_Click(sender, null);
            }
        }
      
        private void textBox_GotFocus(object sender, RoutedEventArgs e)
        {
             (sender as PasswordBox).SelectAll();
        }

        private void btnDeleteMe_Click(object sender, RoutedEventArgs e)
        {
            long deleteUserID = long.Parse((sender as Button).CommandParameter.ToString());
            settings.UserList.RemoveAll(u => u.UserID == deleteUserID);
            settings.Save();
            settings.Reload();
            txtUserName.ItemsSource = settings.UserList;
        }

        private void txtUserName_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (txtUserName.SelectedItem != null)
            {
                txtPassword.Password = Rabbit.Utils.Common.DecryptString(
                    (txtUserName.SelectedItem as UserSettings).TokenSecret);
            }
            else
            {
                txtPassword.Password = "";
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            ResetPanelStatus();
        }

        private void linkGetVerifyCode_Click(object sender, RoutedEventArgs e)
        {
            txtVerifyCode.Focus();
            txtVerifyCode.Clear();
            Action tempDelegate = new Action(() =>
            {
                try
                {
                    string AuthenticationUrl = RequestHelper.GetAuthorizationUrl();
                    Process.Start(AuthenticationUrl);
                }
                catch (Exception ex)
                {
                    LogHelper.LogError(ex);
                    MessageBox.Show("无法连接到搜狐微博，请稍后重试");
                }
            }
            );
            tempDelegate.BeginInvoke(null, null);
        }

        private void linkRegister_Click(object sender, RoutedEventArgs e)
        {
            Rabbit.Utils.Common.OpenWebPage(App.Current.Resources["RegisterPageUrl"].ToString());
        }

        private void linkPasswordRecovery_Click(object sender, RoutedEventArgs e)
        {
            Rabbit.Utils.Common.OpenWebPage(App.Current.Resources["PasswordRecoveryPageUrl"].ToString());
        }

        private void linkMyWebsite_Click(object sender, RoutedEventArgs e)
        {
            Rabbit.Utils.Common.OpenWebPage(App.Current.Resources["MyWebsite"].ToString());
        }
    }
}
